home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Games of Daze
/
Infomagic - Games of Daze (Summer 1995) (Disc 1 of 2).iso
/
x2ftp
/
msdos
/
mxutil
/
tspak17
/
time_div.asm
< prev
next >
Wrap
Assembly Source File
|
1994-08-31
|
5KB
|
227 lines
; TIME_DIV.ASM
;
; External assembler subroutine for Recwav.pas. This routine measures the
; number of bytes transferred in 8 timer ticks (524,288 PIT clock counts, or
; 0.4394 seconds) by the DAC when recording sound using the given input
; divider. The number of bytes is returned. Sound samples are placed in
; the 65535-byte buffer whose pointer is passed to the subroutine.
;
; A Tandy DAC is assumed to be present; time_div() gets its address from
; the BIOS. This subroutine takes over the timer tick and bypasses the
; BIOS, programming the PIT, the DMA controller, and the sound chip directly.
;
; The Turbo Pascal invocation syntax is:
;
; function time_div(
; buffer: (* buffer to fill *)
; pointer;
; divider: (* divider to use *)
; word ):
; word;
;
CODE SEGMENT BYTE PUBLIC
ASSUME CS:CODE,DS:CODE
PUBLIC TIME_DIV
TIME_DIV PROC NEAR
JMP START
;
; Stack frame structure.
;
STACKFRAME STRUC [BP]
OLDBP DW ? ; caller's BP
RETADDR DW ? ; return address
DIVIDER DW ? ; divider for Int 1Ah function 82h
BUFFER DD ? ; pointer to DMA buffer (65535 bytes long)
ENDS
;
; Local variables.
;
FIRSTBYTE DD 0 ; linear address of first byte of buffer
LASTBYTE DD 0 ; linear address of last byte of buffer
DACADDR DW 0 ; base address of the DAC
DMAADDR DW 0 ; DMA starting address
DMAPAGE DB 0 ; DMA 64k page
TICKCOUNT DB 0 ; number of timer ticks since start of DMA
INT08SAVE DD 0 ; previous Int 8 handler
;
; Replacement timer tick interrupt handler.
;
INT08HDLR: PUSH AX
INC CS:TICKCOUNT ; add to count of timer ticks
MOV AL,20h
OUT 20h,AL
POP AX
IRET
;
; Main subroutine.
;
START: PUSH BP ; preserve caller's BP
MOV BP,SP ; and address the parameters
PUSH DS ; save caller's DS
PUSH CS ; DS -> code segment
POP DS
;
; Get DAC base address.
;
MOV AX,8100h
INT 1Ah
MOV DACADDR,AX
;
; Compute starting and ending linear addresses of the buffer.
;
MOV AX,WORD PTR BUFFER
MOV DX,WORD PTR BUFFER+2
MOV CL,4
ROL DX,CL
MOV BX,DX
AND DX,0Fh
AND BX,0FFF0h
ADD AX,BX
ADC DX,0
MOV WORD PTR FIRSTBYTE,AX
MOV WORD PTR FIRSTBYTE+2,DX
ADD AX,65534
ADC DX,0
MOV WORD PTR LASTBYTE,AX
MOV WORD PTR LASTBYTE+2,DX
;
; If the low 16 bits of the address of the first byte is
; less than 32k, there is 32k between the start of the
; buffer and the 64k boundary.
;
CMP WORD PTR FIRSTBYTE,32768
JA USELAST
MOV AX,WORD PTR FIRSTBYTE
MOV DH,BYTE PTR FIRSTBYTE+2
MOV DMAADDR,AX
MOV DMAPAGE,DL
JMP SETDMA
;
; Otherwise, start DMA at the 64k boundary in the middle
; of the buffer.
;
USELAST: MOV DMAADDR,0
MOV AL,BYTE PTR LASTBYTE+2
MOV DMAPAGE,DL
;
; Set up the DMA controller for the transfer.
;
SETDMA: CLI
MOV AL,5 ; disable DMA channel 1
OUT 0Ah,AL
JMP $+2
MOV AL,45h ; select channel 1, write transfer to memory,
OUT 0Bh,AL ; autoinitialization disabled, address incre-
JMP $+2 ; ment, single mode
MOV AL,DMAPAGE
OUT 83h,AL ; set DMA channel 1 page register
JMP $+2
MOV AL,0FFh ; clear byte pointer flip/flop
OUT 0Ch,AL
JMP $+2
MOV AL,-1
OUT 03h,AL ; set DMA channel 1 count to maximum
JMP $+2
OUT 03h,AL
JMP $+2
MOV AX,DMAADDR
OUT 02h,AL ; set DMA channel 1 base address
JMP $+2
MOV AL,AH
OUT 02h,AL
;
; DMA controller is ready to go (when enabled). Set up timer.
;
MOV AL,36h
OUT 43h,AL
JMP $+2
MOV AL,0 ; use maximum count (18.2 ticks/sec)
OUT 40h,AL
JMP $+2
OUT 40h,AL
;
; Timer is ready. Set up sound chip.
;
MOV DX,DACADDR
ADD DX,2
MOV AX,DIVIDER
OUT DX,AL
JMP $+2
INC DX
MOV AL,AH
OUT DX,AL
;
; Sound chip is ready. Hook Int 8.
;
XOR AX,AX
MOV ES,AX
MOV BX,20h
MOV AX,ES:[BX]
MOV WORD PTR INT08SAVE,AX
MOV AX,ES:[BX+2]
MOV WORD PTR INT08SAVE+2,AX
MOV WORD PTR ES:[BX],OFFSET INT08HDLR
MOV ES:[BX+2],CS
MOV TICKCOUNT,0
STI
;
; Wait for two timer ticks.
;
WAIT1: CMP TICKCOUNT,2
JB WAIT1
;
; Enable DMA channel 1 and start sound chip recording.
;
CLI
MOV AL,1
OUT 0Ah,AL
MOV DX,DACADDR
IN AL,DX
JMP $+2
AND AL,0E0h ; recording with DMA, no EOP interrupt
OR AL,6
OUT DX,AL
MOV TICKCOUNT,0
STI
;
; Wait for eight timer ticks.
;
WAIT2: CMP TICKCOUNT,8
JB WAIT2
;
; Stop sound DMA.
;
CLI
MOV DX,DACADDR
IN AL,DX
JMP $+2
AND AL,0FBh
OUT DX,AL
;
; Unhook Int 8. ES:BX -> Int 8 vector still, from above.
;
MOV AX,WORD PTR INT08SAVE
MOV ES:[BX],AX
MOV AX,WORD PTR INT08SAVE+2
MOV ES:[BX+2],AX
;
; Get DMA channel 1 count.
;
MOV AL,0FFh ; clear byte pointer flip/flop
OUT 0Ch,AL
JMP $+2
IN AL,03h
JMP $+2
MOV AH,AL
IN AL,03h
XCHG AL,AH
NOT AX ; return number of bytes transferred in AX
STI
POP DS ; restore caller's DS
POP BP ; restore caller's BP
RET 6 ; discard parameters
TIME_DIV ENDP
CODE ENDS
END